package com.agileai.portal.portlets.grid;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletModeException;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.ProcessAction;
import javax.portlet.ReadOnlyException;
import javax.portlet.RenderMode;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ValidatorException;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.pluto.container.PortletRequestContext;
import org.mvel2.templates.TemplateRuntime;

import com.agileai.common.KeyGenerator;
import com.agileai.domain.DataParam;
import com.agileai.domain.DataRow;
import com.agileai.hotweb.common.BeanFactory;
import com.agileai.portal.bizmoduler.grid.GridFieldsConfigManage;
import com.agileai.portal.driver.AttributeKeys;
import com.agileai.portal.driver.Resource;
import com.agileai.portal.driver.common.PortletRequestHelper;
import com.agileai.portal.driver.common.PreferenceException;
import com.agileai.portal.driver.common.PreferencesHelper;
import com.agileai.portal.driver.common.PreferencesWrapper;
import com.agileai.portal.driver.model.Page;
import com.agileai.portal.driver.model.Theme;
import com.agileai.portal.portlets.BaseMashupPortlet;
import com.agileai.portal.portlets.PortletCacheManager;
import com.agileai.util.StringUtil;

public class DataGridPortlet extends BaseMashupPortlet {
	private static final String DefaultWidth = "900";
	
	@RenderMode(name = "view")
	public void view(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		PortletPreferences preferences =  PreferencesHelper.getPublicPreference(request);
		String height = preferences.getValue("height", null);
		String width = preferences.getValue("width", DefaultWidth);
		String customHead = preferences.getValue("customHead", null);
		
		String pageSize = preferences.getValue("pageSize", null);
		String pageSizeList = preferences.getValue("pageSizeList", null);
		String isStripeRows = preferences.getValue("isStripeRows", "Y");
		String isShowIndexColumn = preferences.getValue("isShowIndexColumn", "N");
		String hasClickCallBack = preferences.getValue("hasClickCallBack","N");
		String callbackFunction = preferences.getValue("callbackFunction","");
		
		request.setAttribute("height", height);
		String parsedWidth = this.parseWidth(request, width);
		request.setAttribute("width", parsedWidth);
		
		request.setAttribute("pageSize", pageSize);
		request.setAttribute("pageSizeList", pageSizeList);
		request.setAttribute("isStripeRows", isStripeRows);
		request.setAttribute("isShowIndexColumn", isShowIndexColumn);
		request.setAttribute("hasClickCallBack",Boolean.valueOf("Y".equals(hasClickCallBack)?true:false));
		request.setAttribute("callbackFunction", callbackFunction);
		

		PortletRequestContext requestContext = PortletRequestHelper.getRequestContext(request);
		Page page = (Page)requestContext.getAttribute(AttributeKeys.PAGE_KEY);
		
		String pageId = page.getPageId();
		String portletId = request.getWindowID();
		request.setAttribute("pageId", pageId);
		request.setAttribute("portletId", portletId);
		
		GridFieldsConfigManage gridFieldsConfigManage = (GridFieldsConfigManage)BeanFactory.instance().getBean("gridFieldsConfigManageService"); 
		List<DataRow> fieldsConfigRecords = gridFieldsConfigManage.findRecords(new DataParam("pageCode",pageId,"portletCode",portletId));
		StringBuffer fieldsBuffer = new StringBuffer();
		StringBuffer colsBuffer = new StringBuffer();
		buildFieldsConfig(fieldsConfigRecords,fieldsBuffer);
		buildColsConfig(fieldsConfigRecords,colsBuffer);
		request.setAttribute("fieldsConfig", fieldsBuffer.toString());
		request.setAttribute("colsConfig", colsBuffer.toString());
		
		if (fieldsBuffer.length() <= 2 || colsBuffer.length() <= 2){
			request.setAttribute("isSetting", "N");
		}else{
			request.setAttribute("isSetting", "Y");
		}
		
		if (customHead != null){
			if (customHead.startsWith("http")){
				String headerURL = getDataURL(request, "customHead");
				String headerHTML = getHeaderHTML(request, headerURL);
				customHead = replaceHeader(headerHTML);
				request.setAttribute("dynamicHead", "Y");
			}else{
				customHead = replaceHeader(customHead);
				request.setAttribute("dynamicHead", "N");
			}
		}
		request.setAttribute("portletId", portletId);
		request.setAttribute("customHead", customHead);
		
		super.doView(request, response);
	}
	
	@SuppressWarnings("rawtypes")
	private String parseWidth(PortletRequest portletRequest,String value){
		String result = value;
		if (value != null){
			if (value.indexOf(Theme.ThemeBodyWidth) > -1){
				String template = value;
				HashMap vars = this.buildVarMap(portletRequest);
				result = String.valueOf(TemplateRuntime.eval(template, vars));
			}
		}
		return result;
	}
	
	@SuppressWarnings({"rawtypes", "unchecked" })
	private HashMap buildVarMap(PortletRequest request){
		HashMap result = new HashMap();
		HttpSession portalSession = PortletRequestHelper.getPortalHttpSession(request);
		if (portalSession != null){
			Theme theme = (Theme)portalSession.getAttribute(Theme.class.getName());
			String themeBodyWidth = null;
			if (Theme.WidthType.Fixed.equals(theme.getWidthType())){
				String width = theme.getWidth();
				String vnavWidth = theme.getVerticalNavWidth();
				themeBodyWidth = String.valueOf(Integer.parseInt(width)- Integer.parseInt(vnavWidth));
			}else{
				String width = (String)portalSession.getAttribute(Theme.WindowScreenWidth);
				String marginWidh = theme.getMarginWidth();
				String vnavWidth = theme.getVerticalNavWidth();
				themeBodyWidth = String.valueOf(Integer.parseInt(width)- Integer.parseInt(marginWidh) - Integer.parseInt(vnavWidth));
			}
			result.put(Theme.ThemeBodyWidth, themeBodyWidth);
		}
		return result;
	}
	
	private String getHeaderHTML(PortletRequest request, String dataURL) {
		String dataXML = "";
		try {
			PortletPreferences preferences = PreferencesHelper.getPublicPreference(request);
			String cacheMinutes = (String)preferences.getValue("cacheMinutes",defaultCacheMinutes);
			String isCache = preferences.getValue("isCache", defaultIsCache);
			dataXML = PortletCacheManager.getOnly().getCachedData(isCache, dataURL, cacheMinutes);
		} catch (Exception e) {
			this.logger.error("retrieve daynamic header html error ", e);
		}
		return dataXML;
	}

	@Resource(id="retrieveHeadHtml")
	public void retrieveHeadHtml(ResourceRequest request, ResourceResponse response)
			throws PortletException, IOException {
		try {
			String headerURL = getDataURL(request, "customHead");
			PortletPreferences preferences = PreferencesHelper.getPublicPreference(request);
			String cacheMinutes = (String)preferences.getValue("cacheMinutes",defaultCacheMinutes);
			String isCache = preferences.getValue("isCache", defaultIsCache);
			String dataXML = PortletCacheManager.getOnly().getCachedData(isCache, headerURL, cacheMinutes);
			
			PrintWriter writer = response.getWriter();
			writer.print(dataXML);
			writer.close();
		} catch (Exception e) {
			this.logger.error("获取取数据JSON失败！", e);
		}
	}
	
	private String replaceHeader(String headerXML) {
		String result = "";
		if (!StringUtil.isNullOrEmpty(headerXML)){
			Pattern p = Pattern.compile("\\t|\r|\n");
			Matcher m = p.matcher(headerXML);
			result = m.replaceAll("");			
		}
		return result;
	}
	
	public static void buildFieldsConfig(List<DataRow> fieldsConfigRecords,StringBuffer fieldsBuffer){
		JSONArray jsonArray = new JSONArray();
		for (int i=0;i < fieldsConfigRecords.size();i++){
			DataRow row = fieldsConfigRecords.get(i);
			String colType = row.getString("FIELD_TYPE");
			if ("col_data".equals(colType)){
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("name",row.stringValue("CODE"));
				jsonArray.add(jsonObject);	
			}
		}
		fieldsBuffer.append(jsonArray.toString());
		
	}
	public static void buildColsConfig(List<DataRow> fieldsConfigRecords,StringBuffer colsBuffer){
		JSONArray jsonArray = new JSONArray();
		for (int i=0;i < fieldsConfigRecords.size();i++){
			DataRow row = fieldsConfigRecords.get(i);
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("id",row.stringValue("CODE"));
			jsonObject.put("header",row.stringValue("NAME"));
			jsonObject.put("width",row.stringValue("WIDTH"));
			jsonObject.put("align",row.stringValue("ALIGN_TYPE"));
			jsonObject.put("headAlign",row.stringValue("HD_ALIGN_TYPE"));
			
			String rendererType = row.stringValue("RENDER_TYPE");
			String rendererFunc = row.stringValue("RENDER_FUNC");
			if (!com.agileai.util.StringUtil.isNullOrEmpty(rendererType) && !com.agileai.util.StringUtil.isNullOrEmpty(rendererFunc)){
				jsonObject.put("renderer","@@@"+rendererFunc+"@@@");				
			}
			String isHidden = row.stringValue("IS_HIDDEN");
			if ("Y".equals(isHidden)){
				jsonObject.put("hidden",true);
			}else{
				jsonObject.put("hidden",false);
			}
			String frozen = row.stringValue("IS_FROZE");
			if ("Y".equals(frozen)){
				jsonObject.put("frozen",true);
			}else{
				jsonObject.put("frozen",false);
			}
			String grouped = row.stringValue("IS_GROUP");
			if ("Y".equals(grouped)){
				jsonObject.put("grouped",true);
			}else{
				jsonObject.put("grouped",false);
			}
			String sortable = row.stringValue("CAN_SORT");
			if ("Y".equals(sortable)){
				jsonObject.put("sortable",true);
			}else{
				jsonObject.put("sortable",false);
			}
			String moveable = row.stringValue("CAN_MOVE");
			if ("Y".equals(moveable)){
				jsonObject.put("resizable",true);
			}else{
				jsonObject.put("resizable",false);
			}
			jsonArray.add(jsonObject);
		}
		String temp = jsonArray.toString();
		temp = temp.replaceAll("\"@@@", "").replaceAll("\r|\n|\t", "");
		temp = temp.replaceAll("@@@\"", "").replaceAll("\r|\n", "");
		colsBuffer.append(temp);
	}
	
	@RenderMode(name = "edit")
	public void edit(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		PortletPreferences preferences =  PreferencesHelper.getPublicPreference(request);
		String defaultVariableValues = preferences.getValue("defaultVariableValues", null);
		String height = preferences.getValue("height", null);
		String width = preferences.getValue("width", DefaultWidth);
		String customHead = preferences.getValue("customHead", null);
		String dataURL = preferences.getValue("dataURL", null);
		String pageSize = preferences.getValue("pageSize", "10");
		String pageSizeList = preferences.getValue("pageSizeList", "10,15,20,25,30,40,50");
//		String isStripeRows = preferences.getValue("isStripeRows", "Y");
//		String isShowIndexColumn = preferences.getValue("isShowIndexColumn", "N");
		String isCache = preferences.getValue("isCache", defaultIsCache);
		String cacheMinutes = preferences.getValue("cacheMinutes", defaultCacheMinutes);
		
		String hasClickCallBack = preferences.getValue("hasClickCallBack","N");
		String callbackFunction = preferences.getValue("callbackFunction","function(value,record,cell,row,rowNo,columnObj,grid,event){}");
		
		request.setAttribute("defaultVariableValues", defaultVariableValues);
		request.setAttribute("height", height);
		request.setAttribute("width", width);
		request.setAttribute("customHead", customHead);
		request.setAttribute("dataURL", dataURL);
		request.setAttribute("pageSize", pageSize);
		request.setAttribute("pageSizeList", pageSizeList);
//		request.setAttribute("isStripeRows", isStripeRows);
//		request.setAttribute("isShowIndexColumn", isShowIndexColumn);
		request.setAttribute("isCache", isCache);
		request.setAttribute("cacheMinutes", cacheMinutes);
		request.setAttribute("hasClickCallBack", hasClickCallBack);
		request.setAttribute("callbackFunction", callbackFunction);
		
		PortletRequestContext requestContext = PortletRequestHelper.getRequestContext(request);
		Page page = (Page)requestContext.getAttribute(AttributeKeys.PAGE_KEY);
		String pageId = page.getPageId();
		String portletId = request.getWindowID();
		request.setAttribute("pageId", pageId);
		request.setAttribute("portletId", portletId);
		super.doEdit(request, response);
		
	}
	
	@ProcessAction(name = "saveConfig")
	public void saveConfig(ActionRequest request, ActionResponse response)
			throws ReadOnlyException, PortletModeException, ValidatorException,IOException, PreferenceException {
		
		String defaultVariableValues = request.getParameter("defaultVariableValues");
		String height = request.getParameter("height");
		String width = request.getParameter("width");
		String customHead = request.getParameter("customHead");
		String dataURL = request.getParameter("dataURL");
		String pageSize = request.getParameter("pageSize");
		String pageSizeList = request.getParameter("pageSizeList");
//		String isStripeRows = request.getParameter("isStripeRows");
//		String isShowIndexColumn = request.getParameter("isShowIndexColumn");
		String isCache = request.getParameter("isCache");
		String cacheMinutes = request.getParameter("cacheMinutes");
		
		String hasClickCallBack = request.getParameter("hasClickCallBack");
		String callbackFunction = request.getParameter("callbackFunction");
		
		PreferencesWrapper preferWapper = new PreferencesWrapper();
		preferWapper.setValue("defaultVariableValues", defaultVariableValues);
		preferWapper.setValue("height", height);
		preferWapper.setValue("width", width);
		preferWapper.setValue("customHead", customHead);
		preferWapper.setValue("dataURL", dataURL);
		preferWapper.setValue("pageSize", pageSize);
		preferWapper.setValue("pageSizeList", pageSizeList);
//		preferWapper.setValue("isStripeRows", isStripeRows);
//		preferWapper.setValue("isShowIndexColumn", isShowIndexColumn);
		preferWapper.setValue("isCache", isCache);
		preferWapper.setValue("cacheMinutes", cacheMinutes);
		preferWapper.setValue("hasClickCallBack", hasClickCallBack);
		preferWapper.setValue("callbackFunction", callbackFunction);
		
		PreferencesHelper.savePublicPreferences(request, preferWapper.getPreferences());	
		response.setPortletMode(PortletMode.VIEW);
	}

	@Resource(id="createFieldConfigId")
	public void createFieldConfigId(ResourceRequest request, ResourceResponse response)
			throws PortletException, IOException {
		try {
			PreferencesWrapper preferWapper = new PreferencesWrapper();
			String fieldsConfigId = KeyGenerator.instance().genKey();
			preferWapper.setValue("fieldsConfigId", fieldsConfigId);
			PreferencesHelper.savePublicPreferences(request, preferWapper.getPreferences());	
			
			PrintWriter writer = response.getWriter();
			writer.print("{id:\""+fieldsConfigId+"\"}");
			writer.close();
		} catch (Exception e) {
			this.logger.error("获取取数据JSON失败！", e);
		}
	}
}